package sm.codec;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

import org.apache.mina.core.buffer.IoBuffer;

import sm.codec.api.Codec;
import sm.codec.api.CodecFactory;
import sm.codec.exception.DecodeException;
import sm.codec.exception.EncodeException;
import sm.codec.type.RC;
import sm.def.Type;

public class RCCodec extends AbstractStructCodec implements Codec {

	@Override
	public void encode(IoBuffer buffer, Object value) throws EncodeException {
		try {
			buffer.put(RC.HEADER.getBytes(CharacterCodec.CHARSET));
		} catch (UnsupportedEncodingException e) {
			throw new EncodeException(e.getMessage(), e, buffer, value);
		}
		RC rc = (RC) value;

		List<Object> objects = rc.getValues();
		for (Object obj : objects) {
			int type = Type.getTypeNumber(obj);
			CodecFactory.getCodec(type).encode(buffer, obj);
		}
	}

	@Override
	public Object decode(IoBuffer buffer) throws DecodeException {
		int headerLength = RC.HEADER.length();
		byte[] header = new byte[headerLength];
		buffer.get(header);
		String headerStr = null;
		try {
			headerStr = new String(header, CharacterCodec.CHARSET);
		} catch (UnsupportedEncodingException e) {

			throw new DecodeException(e.getMessage(), e, buffer);
		}
		if (!headerStr.equals(RC.HEADER)) {
			throw new DecodeException("The header of RC is " + headerStr
					+ ", but should be " + RC.HEADER, buffer);
		}

		List<Object> objects = new ArrayList<Object>();
		while (buffer.hasRemaining()) {
			int pos = buffer.position();
			byte typeByte = buffer.get();
			int type = (typeByte & 0xFF) >>> 4;
			buffer.position(pos);
			Object obj = CodecFactory.getCodec(type).decode(buffer);
			objects.add(obj);
		}
		return new RC(objects);
	}
}
